package ufr_stgi.assistance_conduite;

import java.io.*;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;

import ufr_stgi.assistance_conduite.ecouteur.ProximiteAlerte;
import ufr_stgi.assistance_conduite.modele.Panneau;
import ufr_stgi.assistance_conduite.synchronisation.UploaderPanneaux;
import android.app.Activity;
import android.app.PendingIntent;
import android.content.*;
import android.content.pm.PackageManager;
import android.hardware.Camera;
import android.hardware.Camera.PictureCallback;
import android.media.Ringtone;
import android.media.RingtoneManager;
import android.net.Uri;
import android.os.Bundle;

import android.util.Log;
import android.view.View;
import android.widget.*;
import android.widget.ImageView.ScaleType;

/**
 * Activité qui permet de signaler un nouveau panneau et alerter l'utilisateur
 * lorsqu'il se rapproche d'un panneau connu
 * @author Guillaume MONTAVON & Renaud DAVID (Master 2 RIM)
 */
public class ReconnaissancePanneaux extends Activity {
    private CameraView camView;
    Camera mCamera;
    private MonApplication appli; //application
	private Button boutonPhoto;
	private TextView labelVitesse;
	private TextView vitesse;
	private LinearLayout alerteLayout;
	private ImageView photoAlerte;
	private ImageView photoType;
	private TextView labelAlerte;
	private TextView labelDistanceUser;
	private PictureCallback mPicture;
	private FrameLayout preview;

	private IntentFilter mIntentFilter;
	private ArrayList<PendingIntent> listeProximiteIntent;
	private ProximiteAlerte alerteProximite = null;
	
    // The first rear facing camera
    int defaultCameraId;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Log.i(this.getClass().getName(), "onCreate");
        
        setContentView(R.layout.reconnaissance_panneaux);
		
		appli = (MonApplication)getApplication();
		appli.setRp(this);
		appli.setActivityCourante(this);
		labelVitesse = (TextView) findViewById(R.id.label_vitesse);
		
		vitesse = (TextView) findViewById(R.id.vitesse);
		alerteLayout = (LinearLayout) findViewById(R.id.alertLayout);
		labelAlerte = (TextView) findViewById(R.id.label_alerte);
		labelDistanceUser = (TextView) findViewById(R.id.distance_utilisateur);
		photoAlerte = (ImageView) findViewById(R.id.photo_alerte);
		photoType = (ImageView) findViewById(R.id.photo_type);
		
		if(verifierCamera(this)) {
			
			camView = new CameraView(this);

			preview = (FrameLayout) findViewById(R.id.camera_preview);
			preview.addView(camView,0);
			
			boutonPhoto = (Button) findViewById(R.id.bouton_signaler);
			boutonPhoto.setOnClickListener(
				new View.OnClickListener() {
					@Override
					public void onClick(View v) {
						mCamera.takePicture(null, null, mPicture);
					}
				}
			);
			
			MAJVitesse();
			
			
			//prend une photo
			mPicture = new PictureCallback() {
				@Override
				public void onPictureTaken(byte[] data, Camera camera) {
					
					if(data != null) {
						String nomPhoto = getNouveauNomImage();
						
						File pictureFile = new File(appli.getDossierImage(), nomPhoto);
						
						try {
							FileOutputStream fos = new FileOutputStream(pictureFile);
							fos.write(data);
							fos.flush();
							fos.close();
							
							appli.getBdd().ajouterPanneauTemp(new Panneau(0, appli.getLatitude(), appli.getLongitude(), 0, nomPhoto, 0, appli.getDirection(), 0), false);
							
							if(!appli.isEnCoursSynchro()) {
								Intent intentUploadPanneaux = new Intent(appli, UploaderPanneaux.class); 
								startService(intentUploadPanneaux);
							}
							appli.getMain().MAJCaracteristiques();
							Toast.makeText(appli, "Panneau enregistré", Toast.LENGTH_SHORT).show();
							
						} catch (FileNotFoundException e) {
							Log.d("Erreur", "File not found: " + e.getMessage());
						} catch (IOException e) {
							Log.d("Erreur", "Error accessing file: " + e.getMessage());
						}
						camera.startPreview();
					}
				}
			};

			int nbCamera = Camera.getNumberOfCameras();
			Log.i("nbCamera", nbCamera + " Caméras dispos");
		}
		
		listeProximiteIntent = new ArrayList<PendingIntent>();
		mIntentFilter = new IntentFilter(MonApplication.PROXIMITY_INTENT_ACTION);
		
		MAJAlerteProximite();
		
        
    }

	@Override
	protected void onStart() {
		Log.i(this.getClass().getSimpleName(), "onStart");
		super.onStart();
	}
	
	@Override
	protected void onStop() {
		Log.i(this.getClass().getSimpleName(), "onStop");
		super.onStop();
	}

	@Override
	protected void onDestroy() {
		Log.i(this.getClass().getSimpleName(), "onDestroy");
		super.onDestroy();
		supprimerAlerteProximite();
	}
    
    @Override
    protected void onResume() {
        super.onResume();
        Log.i(this.getClass().getSimpleName(), "onResume");
        mCamera = getCamera(); // Open the default i.e. the first rear facing camera.
        camView.setCamera(mCamera);
    }

    @Override
    protected void onPause() {
        super.onPause();
        Log.i(this.getClass().getSimpleName(), "onPause");
        releaseCamera();
    }
    
	private void releaseCamera() {
		if (mCamera != null){
			camView.setCamera(null);
			mCamera.release(); // release the camera for other applications
			mCamera = null;
		}
	}
    
	public Camera getCamera() {
		Camera c = null;
		try {
			c = Camera.open(); // attempt to get a Camera instance
		}
		catch (Exception e) {
			Log.e("getCamera", e.getMessage());
			e.printStackTrace();
		}		
		return c;
	}
	
	/**
	 * Vérifie que le Smartphone possède une caméra
	 * @param context
	 * @return true si le Smartphone possède une caméra
	 */
	public boolean verifierCamera(Context context) {		
		if (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA))
			return true; // le Smartphone a une caméra
		else
			return false; // le Smartphone n'a pas de caméra
	}	
	
	
	/**
	 * Donne un nom contenant la date et l'heure qui sera utilisé lors de la création d'une nouvelle image
	 * @return
	 */
	public String getNouveauNomImage() {
		return "IMG_"+ new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date()) + ".jpg";
	}
	
	/**
	 * Active le bouton pour signaler un panneau
	 */
	public void activerBouton() {
		boutonPhoto.setEnabled(true);
	}

	/**
	 * Met à jour la vitesse à l'écran
	 */
	public void MAJVitesse() {
		
		if(appli.getLatitude() == 0.0 && appli.getLatitude() == 0.0) {
			labelVitesse.setText(R.string.recherche_gps);
			vitesse.setText("");
			vitesse.setBackgroundResource(R.drawable.satellite);
			boutonPhoto.setEnabled(false);
		}
		else {
			labelVitesse.setText(R.string.label_vitesse);
			vitesse.setBackgroundResource(0);
			vitesse.setText(Math.round(appli.getVitesse()*3.6) + " Km/h");
			boutonPhoto.setEnabled(true);
		}
		
	}
	
	/**
	 * Affiche le panneau le plus proche à l'écran
	 */
	public void MAJAlerte() {
		Log.i("MAJAlerte", "MAJAlerte");
		if(appli.nbPanneauxProches() > 0) {
		
			Panneau p = appli.getPlusProchePanneau();
			
			String libelle = "";
			try {
				libelle = appli.getBdd().getType(p.getIdType()).getLibelle();
			} catch (Exception e) {}
			
			if(p.getIdentifiant() == appli.getPanneauPlusProche()) {
				Log.i("maj MAJAlerte", "maj MAJAlerte");
				labelDistanceUser.setText(p.getDistanceUtilisateur() + " m");
			}
			else {
				
				try {
					Uri uri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION); //ne pas déplacer
					Ringtone r = RingtoneManager.getRingtone(appli, uri); 
					r.play();
				} catch(Exception e) {}
				
				Log.i("alert proximité nouveau panneau", p.getIdentifiant() + " : " + p.getChemin());
				Toast.makeText(appli, p.getIdentifiant() + " : " + p.getChemin(), Toast.LENGTH_LONG);
				
				//panneau danger
				labelAlerte.setText(getResources().getString(R.string.panneau) + " " + libelle);
				labelDistanceUser.setText(p.getDistanceUtilisateur() + " m");
				try {
					photoAlerte.setImageDrawable(appli.redimensionnerImage(new File(appli.getDossierImage(), p.getChemin()), 200));
					photoAlerte.setScaleType(ScaleType.CENTER);
				} catch(Exception e) {
					photoAlerte.setImageDrawable(getResources().getDrawable(R.drawable.inconnu));
				}
				
				try {
					photoType.setImageDrawable(appli.redimensionnerImage(new File(appli.getDossierImage(), appli.getBdd().getType(p.getIdType()).getChemin()), 100));
					photoType.setScaleType(ScaleType.CENTER);
				} catch(Exception e) {
					photoType.setImageDrawable(getResources().getDrawable(R.drawable.inconnu));
				}
				
				alerteLayout.setVisibility(View.VISIBLE);
			}
			
			appli.setPanneauPlusProche(p.getIdentifiant());
		}
		else
			alerteLayout.setVisibility(View.INVISIBLE);		
	}
	
	/**
	 * Creer un listener qui contiendra tous les panneaux se trouvant dans notre zone.
	 * Il alertera l'application lorsqu'on sera proche d'un panneaux (moins de 50m)
	 */
	public void MAJAlerteProximite() {
		
		supprimerAlerteProximite();
		
		alerteProximite = new ProximiteAlerte(appli);
		registerReceiver(alerteProximite, mIntentFilter);
		
		for(Panneau p : appli.getBdd().getListePanneau(false, appli.getLatitude(), appli.getLongitude())) {
			//Log.i("MAJAlerteProximite", "MAJAlerteProximite : " + appli.getBdd().getListePanneau(true, appli.getLatitude(), appli.getLongitude()).size());
			Intent intent = new Intent(MonApplication.PROXIMITY_INTENT_ACTION);
			intent.putExtra(MonApplication.PROXIMITY_ID_INTENT_EXTRA, p.getIdentifiant());
			PendingIntent pendingIntent = PendingIntent.getBroadcast(getApplicationContext(), (int) p.getIdentifiant(), intent, PendingIntent.FLAG_CANCEL_CURRENT);
			
			appli.getLocManager().addProximityAlert(p.getLatitude(), p.getLongitude(), MonApplication.PROXIMITY_RAYON_ALERT_METRE, MonApplication.PROXIMITY_EXPIRATION, pendingIntent);
			listeProximiteIntent.add(pendingIntent);	
		}
		
		Log.i("MAJAlerteProximite", "MAJAlerteProximite : " + appli.getBdd().getListePanneau(false, appli.getLatitude(), appli.getLongitude()).size());
		
	}
	
	/**
	 * Supprime le listener qui alerte lorsqu'on est proche d'un panneau
	 */
	public void supprimerAlerteProximite() {
		
		if(alerteProximite != null) {
			try {
				unregisterReceiver(alerteProximite);
			} catch(Exception e) {}
			
			if(listeProximiteIntent.size() > 0) {
				
				for(PendingIntent pi : listeProximiteIntent)
					appli.getLocManager().removeProximityAlert(pi);
				listeProximiteIntent.clear();
			}
			
		}
	}
    
}